package com.crazypos.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crazypos.common.utils.RedisUtil;
import com.crazypos.common.utils.SecurityUtil;
import com.crazypos.constant.CommonConstant;
import com.crazypos.constant.UserTypeConstant;
import com.crazypos.dao.MenuDao;
import com.crazypos.dao.ModuleDao;
import com.crazypos.dao.RoleMenuDao;
import com.crazypos.enums.CanDelete;
import com.crazypos.enums.MenuStatus;
import com.crazypos.enums.ModuleStatus;
import com.crazypos.enums.YesOrNo;
import com.crazypos.exceptions.MyException;
import com.crazypos.pojo.MenuEntity;
import com.crazypos.pojo.ModuleEntity;
import com.crazypos.pojo.RoleMenuEntity;
import com.crazypos.pojo.bo.AdminCreateMenuBO;
import com.crazypos.pojo.bo.AdminDeleteMenuBO;
import com.crazypos.pojo.bo.AdminUpdateMenuBO;
import com.crazypos.pojo.vo.RoleMenuVO;
import com.crazypos.pojo.vo.RoleMenuVO2;
import com.crazypos.security.entity.UserDetailEntity;
import com.crazypos.service.IMenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MenuService extends ServiceImpl<MenuDao, MenuEntity> implements IMenuService {

    @Autowired
    private MenuDao menuDao;

    @Autowired
    private ModuleDao moduleDao;

    @Autowired
    private RoleMenuDao roleMenuDao;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<MenuEntity> getAllMenu(Integer moduleId, Integer status, String keyword) {
        QueryWrapper<MenuEntity> queryWrapper = new QueryWrapper<>();
        if (moduleId != null && moduleId > 0) {
            queryWrapper.eq("module_id", moduleId);
        }

        if (status != null && status >= 0) {
            queryWrapper.eq("status", status);
        }

        if (!StringUtils.isBlank(keyword)) {
            queryWrapper.like("name", keyword);
        }
        return menuDao.selectList(queryWrapper);
    }

    @Override
    public void createMenu(AdminCreateMenuBO bo) {
        ModuleEntity moduleEntity = moduleDao.selectOne(
                new QueryWrapper<ModuleEntity>()
                        .eq("id", bo.getModuleId())
                        .eq("status", MenuStatus.NORMAL.getValue())
        );

        if (moduleEntity == null) {
            throw new MyException(404, "module不存在");
        }
        MenuEntity menuEntity = new MenuEntity();
        BeanUtils.copyProperties(bo, menuEntity);
        if (bo.getCanDelete() == null) {
            menuEntity.setCanDelete(CanDelete.YES.getValue());
        }
        menuEntity.setModuleName(moduleEntity.getName());
        menuEntity.setStatus(MenuStatus.NORMAL.getValue());

        menuDao.insert(menuEntity);
    }

    @Override
    @Transactional
    public void updateMenu(AdminUpdateMenuBO bo) {
        int menuIsExist = menuDao.selectCount(
                new QueryWrapper<MenuEntity>()
                        .eq("id", bo.getId())
        );

        if (menuIsExist == 0) {
            throw new MyException(404, "menu不存在");
        }

        ModuleEntity moduleEntity = moduleDao.selectOne(
                new QueryWrapper<ModuleEntity>()
                        .eq("id", bo.getModuleId())
                        .eq("status", ModuleStatus.NORMAL.getValue())
        );

        if (moduleEntity == null) {
            throw new MyException(404, "module不存在");
        }

        MenuEntity menuEntity = new MenuEntity();
        BeanUtils.copyProperties(bo, menuEntity);
        menuEntity.setModuleName(moduleEntity.getName());
        menuDao.updateById(menuEntity);

        updateRedisMenus(bo.getId());

    }

    @Override
    public void deleteMenu(AdminDeleteMenuBO bo) {
        Integer id = bo.getId();
        int isExist = menuDao.selectCount(
                new QueryWrapper<MenuEntity>()
                        .eq("id", id)
                        .eq("can_delete", CanDelete.YES.getValue())
                        .eq("status", ModuleStatus.NORMAL.getValue())
        );
        if (isExist == 0) {
            throw new MyException(404, "module不存在或者已经删除");
        }

        MenuEntity entity = new MenuEntity();
        entity.setId(id);
        entity.setStatus(ModuleStatus.DISABLED.getValue());
        menuDao.updateById(entity);
    }

    @Override
    public List<MenuEntity> getAllMenus() {
        UserDetailEntity loginUser = SecurityUtil.getUserInfo();
        QueryWrapper<MenuEntity> queryWrapper = new QueryWrapper();
        if(!loginUser.getType().equals(UserTypeConstant.ADMIN)){
            queryWrapper.ne("is_admin",1);
        }
        queryWrapper.eq("status",1);
        return menuDao.selectList(queryWrapper);
    }

    /***
     * 更新redis的菜单
     */
    private void updateRedisMenus(Integer menuId) {
        // 查询到与该menuId关联的roleId, 然后清除这些role的菜单缓存
        List<RoleMenuEntity> roleMenuList = roleMenuDao.selectList(
                new QueryWrapper<RoleMenuEntity>()
                        .select("DISTINCT role_id,menu_id")
                        .eq("menu_id", menuId)
        );

        List<String> roleIds = roleMenuList.stream()
                .map(item -> item.getRoleId()).collect(Collectors.toList());

        if (roleIds.size() > 0) {
            for (String roleId :
                    roleIds) {
                // 查询导航菜单
                List<RoleMenuVO2> roleMenuVOS = menuDao.getMenusByRoleId(roleId);
                List<RoleMenuVO> navMenus = new ArrayList<>();
                List<RoleMenuVO> roleMenus = new ArrayList<>();
                roleMenuVOS.stream().forEach(item -> {
                    if (item.getType() == 1) {
                        // 导航菜单
                        navMenus.add(item);
                    } else if (item.getType() == 2) {
                        // 权限菜单
                        roleMenus.add(item);
                    }
                });

                // 将新建的ROLE存储到REDIS
                String key = SecurityUtil.createPermissionKey("", roleId);

                redisUtil.hset(key, CommonConstant.NAV_MENUS_NAME, JSON.toJSONString(navMenus));
                redisUtil.hset(key, CommonConstant.ROLE_MENUS_NAME, JSON.toJSONString(roleMenus));

            }
        }
    }
}
